/**
 * Copyright 2018 asiainfo Inc.
 **/
package com.myz.service.feign.feign;

import com.myz.service.feign.feign.impl.ScheduleUploadServiceHystrix;
import feign.Logger;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;


/**
 * 通过@FeignClient（“服务名”），来指定调用哪个服务 spring.application.name
 * 参数url指定服务端地址
 * fallback:
 *
 * @author maoyz on 2018/9/7
 * @version: v1.0
 */
@FeignClient(value = "http://SERVICE-MEMBER",
        configuration = {ScheduleUploadService.MultipartSupportConfig.class},
        fallback = ScheduleUploadServiceHystrix.class,
        fallbackFactory = ScheduleUploadServiceFallbackFactory.class,
        path = "/member")
public interface ScheduleUploadService {

    /**
     * 文件上传, 使用@RequestPart
     *
     * @param file 上传文件
     * @return 上传信息
     */
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    String handleFileUpload(@RequestPart(value = "file") MultipartFile file);

    class MultipartSupportConfig {

        @Autowired
        private ObjectFactory<HttpMessageConverters> messageConverters;

        /**
         * feign.codec.EncodeException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] and content type [multipart/form-data]
         *
         * @return
         */
        @Bean
        @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        @Primary
        public Encoder feignFormEncoder() {
            return new SpringFormEncoder(new SpringEncoder(messageConverters));
        }

        // 开启Feign的日志
        @Bean
        public Logger.Level logger() {
            return Logger.Level.FULL;
        }
    }

    @Slf4j
    @Component
    class ScheduleUploadServiceFallbackFactory implements FallbackFactory<ScheduleUploadService> {

        @Override
        public ScheduleUploadService create(Throwable cause) {
            log.error("ScheduleUploadServiceFallbackFactory error:", cause);

            return new ScheduleUploadService() {

                @Override
                public String handleFileUpload(MultipartFile file) {
                    return "ScheduleUploadService FallbackFactory";
                }
            };
        }
    }

}
